/**
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package edu.uci.ics.crawler4j.url;

import java.io.Serializable;

import com.sleepycat.persist.model.Entity;
import com.sleepycat.persist.model.PrimaryKey;

/**
 * @author Yasser Ganjisaffar <lastname at gmail dot com>
 */
@Entity
public class WebURL implements Serializable
{

    private static final long serialVersionUID = 862597602391131493L;

    @PrimaryKey
    private String url;

    private int docid;
    private int parentDocid;
    private String parentUrl;
    private short depth;
    private String domain;
    private String subDomain;
    private String path;
    private String anchor;
    private byte priority;

    /**
     * Returns the unique document id assigned to this Url.
     */
    public int getDocid()
    {
        return docid;
    }

    public void setDocid(int docid)
    {
        this.docid = docid;
    }

    /**
     * Returns the Url string
     */
    public String getURL()
    {
        return url;
    }

    public void setURL(String url)
    {
        this.url = url;

        int domainStartIdx = url.indexOf("//") + 2;
        int domainEndIdx = url.indexOf('/', domainStartIdx);
        domain = url.substring(domainStartIdx, domainEndIdx);
        subDomain = "";
        String[] parts = domain.split("\\.");
        if (parts.length > 2) {
            domain = parts[parts.length - 2] + "." + parts[parts.length - 1];
            int limit = 2;
            if (TLDList.contains(domain)) {
                domain = parts[parts.length - 3] + "." + domain;
                limit = 3;
            }
            for (int i = 0; i < parts.length - limit; i++) {
                if (subDomain.length() > 0) {
                    subDomain += ".";
                }
                subDomain += parts[i];
            }
        }
        path = url.substring(domainEndIdx);
        int pathEndIdx = path.indexOf('?');
        if (pathEndIdx >= 0) {
            path = path.substring(0, pathEndIdx);
        }
    }

    /**
     * Returns the unique document id of the parent page. The parent page is the page in which the
     * Url of this page is first observed.
     */
    public int getParentDocid()
    {
        return parentDocid;
    }

    public void setParentDocid(int parentDocid)
    {
        this.parentDocid = parentDocid;
    }

    /**
     * Returns the url of the parent page. The parent page is the page in which the Url of this page
     * is first observed.
     */
    public String getParentUrl()
    {
        return parentUrl;
    }

    public void setParentUrl(String parentUrl)
    {
        this.parentUrl = parentUrl;
    }

    /**
     * Returns the crawl depth at which this Url is first observed. Seed Urls are at depth 0. Urls
     * that are extracted from seed Urls are at depth 1, etc.
     */
    public short getDepth()
    {
        return depth;
    }

    public void setDepth(short depth)
    {
        this.depth = depth;
    }

    /**
     * Returns the domain of this Url. For 'http://www.example.com/sample.htm', domain will be
     * 'example.com'
     */
    public String getDomain()
    {
        return domain;
    }

    public String getSubDomain()
    {
        return subDomain;
    }

    /**
     * Returns the path of this Url. For 'http://www.example.com/sample.htm', path will be
     * 'sample.htm'
     */
    public String getPath()
    {
        return path;
    }

    public void setPath(String path)
    {
        this.path = path;
    }

    /**
     * Returns the anchor string. For example, in <a href="example.com">A sample anchor</a> the
     * anchor string is 'A sample anchor'
     */
    public String getAnchor()
    {
        return anchor;
    }

    public void setAnchor(String anchor)
    {
        this.anchor = anchor;
    }

    /**
     * Returns the priority for crawling this URL. A lower number results in higher priority.
     */
    public byte getPriority()
    {
        return priority;
    }

    public void setPriority(byte priority)
    {
        this.priority = priority;
    }

    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((anchor == null) ? 0 : anchor.hashCode());
        result = prime * result + depth;
        result = prime * result + docid;
        result = prime * result + ((domain == null) ? 0 : domain.hashCode());
        result = prime * result + parentDocid;
        result = prime * result + ((parentUrl == null) ? 0 : parentUrl.hashCode());
        result = prime * result + ((path == null) ? 0 : path.hashCode());
        result = prime * result + priority;
        result = prime * result + ((subDomain == null) ? 0 : subDomain.hashCode());
        result = prime * result + ((url == null) ? 0 : url.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        WebURL other = (WebURL) obj;
        if (anchor == null) {
            if (other.anchor != null)
                return false;
        } else if (!anchor.equals(other.anchor))
            return false;
        if (depth != other.depth)
            return false;
        if (docid != other.docid)
            return false;
        if (domain == null) {
            if (other.domain != null)
                return false;
        } else if (!domain.equals(other.domain))
            return false;
        if (parentDocid != other.parentDocid)
            return false;
        if (parentUrl == null) {
            if (other.parentUrl != null)
                return false;
        } else if (!parentUrl.equals(other.parentUrl))
            return false;
        if (path == null) {
            if (other.path != null)
                return false;
        } else if (!path.equals(other.path))
            return false;
        if (priority != other.priority)
            return false;
        if (subDomain == null) {
            if (other.subDomain != null)
                return false;
        } else if (!subDomain.equals(other.subDomain))
            return false;
        if (url == null) {
            if (other.url != null)
                return false;
        } else if (!url.equals(other.url))
            return false;
        return true;
    }

    @Override
    public String toString()
    {
        StringBuilder builder = new StringBuilder();
        builder.append("WebURL [url=").append(url).append(", docid=").append(docid).append(", parentDocid=").append(
                parentDocid).append(", parentUrl=").append(parentUrl).append(", depth=").append(depth).append(
                ", domain=").append(domain).append(", subDomain=").append(subDomain).append(", path=").append(path).append(
                ", anchor=").append(anchor).append(", priority=").append(priority).append("]");
        return builder.toString();
    }

}
